<template>
  <div class="particles-container" ref="particlesContainer">
    <canvas ref="particlesCanvas"></canvas>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

const particlesContainer = ref<HTMLDivElement | null>(null)
const particlesCanvas = ref<HTMLCanvasElement | null>(null)
let animationFrameId: number | null = null

interface Particle {
  x: number
  y: number
  size: number
  speedX: number
  speedY: number
  opacity: number
  hue: number
}

const particles: Particle[] = []
const particleCount = 50
const particleBaseSize = 3
const connectionDistance = 150
let ctx: CanvasRenderingContext2D | null = null
let width = 0
let height = 0

const createParticle = (): Particle => ({
  x: Math.random() * width,
  y: Math.random() * height,
  size: Math.random() * particleBaseSize + 1,
  speedX: (Math.random() - 0.5) * 0.2,
  speedY: (Math.random() - 0.5) * 0.2,
  opacity: Math.random() * 0.5 + 0.2,
  hue: Math.random() * 40 + 200
})

const initParticles = () => {
  particles.length = 0
  for (let i = 0; i < particleCount; i++) {
    particles.push(createParticle())
  }
}

const updateParticles = () => {
  particles.forEach(particle => {
    particle.x += particle.speedX
    particle.y += particle.speedY

    if (particle.x < 0 || particle.x > width) particle.speedX *= -1
    if (particle.y < 0 || particle.y > height) particle.speedY *= -1
    
    particle.x = Math.max(0, Math.min(width, particle.x))
    particle.y = Math.max(0, Math.min(height, particle.y))
  })
}

const drawParticles = () => {
  if (!ctx) return

  ctx.clearRect(0, 0, width, height)

  particles.forEach(particle => {
    const gradient = ctx!.createRadialGradient(
      particle.x, particle.y, 0,
      particle.x, particle.y, particle.size * 2
    )
    gradient.addColorStop(0, `hsla(${particle.hue}, 80%, 60%, ${particle.opacity})`)
    gradient.addColorStop(1, `hsla(${particle.hue}, 80%, 60%, 0)`)
    
    ctx!.beginPath()
    ctx!.arc(particle.x, particle.y, particle.size * 2, 0, Math.PI * 2)
    ctx!.fillStyle = gradient
    ctx!.fill()

    particles.forEach(otherParticle => {
      const dx = particle.x - otherParticle.x
      const dy = particle.y - otherParticle.y
      const distance = Math.sqrt(dx * dx + dy * dy)

      if (distance < connectionDistance) {
        const opacity = (1 - distance / connectionDistance) * 0.15
        ctx!.beginPath()
        ctx!.moveTo(particle.x, particle.y)
        ctx!.lineTo(otherParticle.x, otherParticle.y)
        
        const gradient = ctx!.createLinearGradient(
          particle.x, particle.y,
          otherParticle.x, otherParticle.y
        )
        gradient.addColorStop(0, `hsla(${particle.hue}, 80%, 60%, ${opacity})`)
        gradient.addColorStop(1, `hsla(${otherParticle.hue}, 80%, 60%, ${opacity})`)
        
        ctx!.strokeStyle = gradient
        ctx!.lineWidth = 1
        ctx!.stroke()
      }
    })
  })
}

const animate = () => {
  updateParticles()
  drawParticles()
  animationFrameId = requestAnimationFrame(animate)
}

const handleResize = () => {
  if (!particlesCanvas.value || !particlesContainer.value) return

  width = particlesContainer.value.clientWidth
  height = particlesContainer.value.clientHeight
  particlesCanvas.value.width = width
  particlesCanvas.value.height = height
  initParticles()
}

onMounted(() => {
  if (!particlesCanvas.value) return

  ctx = particlesCanvas.value.getContext('2d')
  handleResize()
  window.addEventListener('resize', handleResize)
  animate()
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  if (animationFrameId !== null) {
    cancelAnimationFrame(animationFrameId)
  }
})
</script>

<style scoped>
.particles-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
  opacity: 0.6;
}

canvas {
  display: block;
  width: 100%;
  height: 100%;
  filter: blur(0.5px);
}
</style>
